package com.tanhua.dubbo.server.api;

import com.alibaba.dubbo.config.annotation.Service;
import com.tanhua.dubbo.server.pojo.ActiveUser;
import com.tanhua.dubbo.server.pojo.UserLog;
import com.tanhua.dubbo.server.vo.UsersCountVo;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

@Service(version = "1.0.0")
public class UsersCountApiImpl implements UsersCountApi {

    @Autowired
    private MongoTemplate mongoTemplate;

    //查询用户活跃表和用户日志表获取数据
    @Override
    public UsersCountVo select() {
        long nowTime = new Date().getTime();//获取当前时间Long类型
        String dateStr = new DateTime().toString("yyyyMMdd");
        //今日日期
        Integer dateToday = Integer.valueOf(dateStr);
        //昨日日期
        Integer dateYesterday = Integer.valueOf(new DateTime(new Date(nowTime - 24 * 3600 * 1000)).toString("yyyyMMdd"));
        //七日前日期
        Integer datePassWeek = Integer.valueOf(new DateTime(new Date(nowTime - 7 * 24 * 3600 * 1000)).toString("yyyyMMdd"));
        //三十日日期
        Integer datePassMonth = Integer.valueOf(new DateTime(new Date(nowTime - 30L * 24 * 3600 * 1000)).toString("yyyyMMdd"));
        //获取今日登录总次数,包含一个用户多次登录
        Query query = Query.query(Criteria.where("type").is(1));
        Integer loginTimesToday = (int) mongoTemplate.count(query, UserLog.class, "user_log_" + dateToday);
        //昨日登录次数
        Integer loginTimesYesterday = (int) mongoTemplate.count(query, UserLog.class, "user_log_" + dateYesterday);
        //今日登录次数增长率
        Integer rate = (int) ((loginTimesToday - loginTimesYesterday) / (loginTimesYesterday * 1.0) * 100);
        Integer loginTimesTodayRate = (int) rate;
        //今日活跃用户
        Query activeQuery1 = Query.query(Criteria.where("loginDate").is(dateToday));
        Integer activeUsersToday = (int) mongoTemplate.count(activeQuery1, ActiveUser.class);
        //昨日活跃用户
        Query activeQuery2 = Query.query(Criteria.where("loginDate").is(dateYesterday));
        Integer activeUsersYesterday = (int) mongoTemplate.count(activeQuery2, ActiveUser.class);
        //前天活跃用户,用于计算昨日活跃增长率
        Integer datePassThreeDay = Integer.valueOf(new DateTime(new Date(nowTime - 3 * 24 * 3600 * 1000)).toString("yyyyMMdd"));
        Query activeQuery = Query.query(Criteria.where("loginDate").is(datePassThreeDay));
        Integer activeUsersPassThreeDay = (int) mongoTemplate.count(activeQuery, ActiveUser.class);
        //7天活跃用户
        Query activeQuery3 = Query.query(Criteria.where("loginDate").gt(datePassWeek));
        List<ActiveUser> activeUserList = mongoTemplate.find(activeQuery3, ActiveUser.class);
        Integer activePassWeek = activeUserList.size();
        //30天活跃用户
        Query activeQuery4 = Query.query(Criteria.where("loginDate").gt(datePassMonth));
        Integer activePassMonth = (int) mongoTemplate.count(activeQuery4, ActiveUser.class);
        //过去7天使用总时长
        long userTimeSum = 0L;
        for (ActiveUser activeUser : activeUserList) {
            userTimeSum += activeUser.getOperateTime();
        }
        Integer userTimePassWeek = (int) (userTimeSum / 7.0) - (8 * 3600 * 1000);
        //今日活跃用户增长率
        Integer activeUsersTodayRate = (int) ((activeUsersToday - activeUsersYesterday) / (activeUsersYesterday * 1.0) * 100);
        //昨日活跃用户增长率
        Integer activeUsersYesterdayRate = (int) ((activeUsersYesterday - activeUsersPassThreeDay) / (activeUsersPassThreeDay * 1.0) * 100);
        UsersCountVo usersCountVo = new UsersCountVo();
        usersCountVo.setUseTimePassWeek(userTimePassWeek);
        usersCountVo.setActivePassWeek(activePassWeek);
        usersCountVo.setActivePassMonth(activePassMonth);
        usersCountVo.setActiveUsersToday(activeUsersToday);
        usersCountVo.setActiveUsersYesterday(activeUsersYesterday);
        usersCountVo.setActiveUsersTodayRate(activeUsersTodayRate);
        usersCountVo.setActiveUsersYesterdayRate(activeUsersYesterdayRate);
        usersCountVo.setLoginTimesToday(loginTimesToday);
        usersCountVo.setLoginTimesTodayRate(loginTimesTodayRate);
        return usersCountVo;
    }

    /*
     * 例如  20210619~20210719
     * start 起始时间
     * end   截止时间
     * */
    @Override
    public List<ActiveUser> usersCount(Long start, Long end) {
        //查询得到时间段内的活跃总人数,同一用户去重(只保留第一次登录日期)
        Query query = Query.query(Criteria.where("firstLoginTime").gt(start).lt(end))
                .with(Sort.by(Sort.Order.asc("loginDate")));//按日期正序排列,方便去重*/
        List<ActiveUser> activeUserList = mongoTemplate.find(query, ActiveUser.class);

        // 根据activeUserList中的userId来去重
        List<ActiveUser> resultList = null;
        try {
            resultList = activeUserList.stream().filter(distinctByKey(ActiveUser::getUserId)).collect(Collectors.toList());
            return resultList;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    //去重
    private static <T> Predicate<T> distinctByKey(Function<? super T, Object> keyExtractor) {
        Map<Object, Boolean> seen = new ConcurrentHashMap<>();
        return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
    }

}
